package com.sihai.gateway.predicate.factory;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sihai.gateway.predicate.RoutePredicate;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StreamUtils;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.NotEmpty;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Route predicate by parameter.
 *
 * @author sihai
 */
@Slf4j
public class BodyRoutePredicateFactory
        extends AbstractRoutePredicateFactory<BodyRoutePredicateFactory.Config> {

    public BodyRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public RoutePredicate create(Config config) {
        return request -> {

            byte[] requestBody = new byte[0];
            try {
                requestBody = StreamUtils.copyToByteArray(request.getInputStream());

                Map<String, Object> body = getParameterMap(requestBody);
                if (CollectionUtils.isEmpty(body)) {
                    return false;
                }
                else {
                    Map<String, String> configParameters = config.getBody();
                    for (Entry<String, String> configParameterEntry : configParameters.entrySet()) {
                        String configParameterName = configParameterEntry.getKey();
                        // 配置文件中存放的值
                        String configParameterRegexp = configParameterEntry.getValue();
                        // 只要前端的值与这个匹配，放行。反之，驳回
                        //String[] okSms = configParameterRegexp.split(",");
                        String[] okSms = configParameterRegexp.split(" ");
                        String condition = okSms[0];
                        Object o=  body.get(configParameterName);
                        String value = okSms[1];
                        if(condition.equals("in"))
                        {
                            ArrayList<String> values = new ArrayList<>();
                            String[] smss = value.split(",");
                            for(String sms:smss)
                            {
                                if(sms.matches("[A-Z]0{6}\\d")) {
                                    values.add(sms);
                                }
                            }
                            if(!ObjectUtils.isEmpty(o) && values.contains(o.toString())){
                                return true;
                            }
                        }
                        else if(condition.equals("bigger"))
                        {
                            Long l = Long.valueOf(value);
                            if(!ObjectUtils.isEmpty(o) && Long.valueOf(String.valueOf(o))>l){
                                return true;
                            }
                        }
                        else if(condition.equals("less"))
                        {
                            Long l = Long.valueOf(value);
                            if(!ObjectUtils.isEmpty(o) && Long.valueOf(String.valueOf(o))<l){
                                return true;
                            }
                        }
                        else if(condition.equals("range"))
                        {

                            String[] range  = value.split(",");
                            Long l = Long.valueOf(range[0]);
                            Long r = Long.valueOf(range[1]);
                            if(!ObjectUtils.isEmpty(o) && Long.parseLong(String.valueOf(o))<r&&Long.valueOf(String.valueOf(o))>=l){
                                return true;
                            }
                        }

                    }

                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return false;
        };
    }

    @Data
    @Validated
    public static class Config {

        /**
         * Predicate with request parameters
         *
         * <pre>
         * key: parameter name
         * value: regexp expression
         * </pre>
         */
        @NotEmpty
        private Map<String, String> body;
    }

    public static Map<String, Object> getParameterMap(byte[] params) throws UnsupportedEncodingException {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(params, Map.class);
        } catch (Exception e) {
            // 有可能是表单数据
            log.error("转换为Map对象发生错误，请检查传入的参数....");
            log.error(e.getMessage());
            return null;
        }
    }
}
